/*
* BSM6.0
 *
 * Copyright 2012-2013 (C) SINODATA CO., LTD. All Rights Reserved.
 */
package com.sinodata.bsm.center.web.action.integration;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.springframework.beans.factory.annotation.Autowired;

import com.sinodata.bsm.center.bean.ResTypeBean;
import com.sinodata.bsm.center.cache.ProbeCache;
import com.sinodata.bsm.center.cache.ResAttrValCache;
import com.sinodata.bsm.center.cache.ResCache;
import com.sinodata.bsm.center.cache.ResRelationCache;
import com.sinodata.bsm.center.cache.ResTypeCache;
import com.sinodata.bsm.center.engine.resource.find.FindResBean;
import com.sinodata.bsm.center.engine.resource.find.FindResFactory;
import com.sinodata.bsm.center.engine.resource.find.FindResGroup;
import com.sinodata.bsm.center.message.Messenger;
import com.sinodata.bsm.center.service.probe.ProbeService;
import com.sinodata.bsm.center.service.relation.ResRelationService;
import com.sinodata.bsm.center.service.resource.AttributeService;
import com.sinodata.bsm.center.service.resource.ResService;
import com.sinodata.bsm.center.util.web.Struts2Utils;
import com.sinodata.bsm.center.web.action.BaseAction;
import com.sinodata.bsm.common.constants.RelationConstants;
import com.sinodata.bsm.common.constants.ResConstants;
import com.sinodata.bsm.common.message.ServiceMessage;
import com.sinodata.bsm.common.vo.Attribute;
import com.sinodata.bsm.common.vo.Probe;
import com.sinodata.bsm.common.vo.Res;
import com.sinodata.bsm.common.vo.ResAttrVal;
import com.sinodata.bsm.common.vo.ResRelation;

/**
 * <p>
 * Description: 
 * </p>
 *
 * @author wangyazhou
 * @version 1.0

 * <p>
 * History: 
 *
 * Date                     Author         Version     Description
 * ---------------------------------------------------------------------------------
 * 2013-5-17 下午4:48:24          wangyazhou        1.0         To create
 * </p>
 *
 * @since 
 * @see     
 */
public class InmpopAction extends BaseAction<Object> {

    private static final long serialVersionUID = 1L;
    private static Map<String, String> changeMap = new HashMap<String, String>();

    private Long id;

    private Res entity;
    @Autowired
    private ResCache resCache;
    @Autowired
    private ResTypeCache resTypeCache;
    @Autowired
    private ResAttrValCache resAttrValCache;
    @Autowired
    private ProbeCache probeCache;
    @Autowired
    private ResRelationCache resRelationCache;
    @Autowired
    private ProbeService probeService;
    @Autowired
    private ResService resService;
    @Autowired
    private AttributeService attributeService;
    @Autowired
    private ResRelationService resRelationService;

    private static Map<String, String[]> typeMap = new ConcurrentHashMap<String, String[]>();
    private static Map<String, String[]> subTypeMap = new ConcurrentHashMap<String, String[]>();

    @SuppressWarnings("unchecked")
    public String guide() {
        List<Probe> probeList = probeService.findAllInmpProbe();
        Collections.sort(probeList, new ProbeSort());
        request.setAttribute("probeList", probeList);
        request.setAttribute("id", id);
        request.setAttribute("viewId", request.getParameter("viewId"));

        System.out.println();
        return "guide";
    }

    /**
     * 获取所有可集成的资源列表
     * @return
     */
    public String getNetDeviceList() {
        String probeId = request.getParameter("probeId");
        String flag = request.getParameter("flag");
        try {
            if (probeId.equals("")) {
                JSONObject json = new JSONObject();
                json.element("iTotalRecords", 0);
                json.element("iTotalDisplayRecords", 0);
                JSONArray array = new JSONArray();
                json.element("aaData", array);
                renderText(json.toString());
            } else {
                List<String[]> list = getNwList(Long.parseLong(probeId), "getNetDeviceList", null);

                if (list == null) {
                    JSONObject json = new JSONObject();
                    json.element("iTotalRecords", 0);
                    json.element("iTotalDisplayRecords", 0);
                    JSONArray array = new JSONArray();
                    json.element("aaData", array);
                    renderText(json.toString());
                    return null;
                }
                JSONObject json = new JSONObject();
                json.element("iTotalRecords", list.size());
                json.element("iTotalDisplayRecords", list.size());
                JSONArray array = new JSONArray();
                for (String[] sy : list) {
                    JSONObject obj = new JSONObject();
                    //如果缓存中存在这个资源  并且已存在的资源不在此视图下
                    //                    Res res = resCache.getResByIpType(sy[3], Long.parseLong(sy[4]));
                    //                    if (res != null) {
                    //                        obj.element("probeName", "<div style='color:gray;text-decoration:line-through;'>" + probeCache.get(Long.parseLong(probeId)).getName() + "</div>");
                    //                        obj.element("resName", "<div style='color:gray;text-decoration:line-through;'>" + sy[1] + "</div>");
                    //                        obj.element("ip", "<div style='color:gray;text-decoration:line-through;'>" + sy[3] + "</div>");
                    //                        obj.element("resTypeName", "<div style='color:gray;text-decoration:line-through;'>" + resTypeCache.get(Long.parseLong(sy[4])).getName() + "</div>");
                    //                        if (flag.equals("0")) {
                    //                            if (sy[0].equals(res.getInternalId())) {
                    //                                obj.element("change", "已存在,只需重新发现");
                    //                            } else {
                    //                                obj.element("change", "已存在,但需重新添加");
                    //                            }
                    //                        } else {
                    //                            obj.element("change", "<div style='color:gray;text-decoration:line-through;'>" + changeMap.get(sy[0]) == null ? "" : changeMap.get(sy[0]) + "</div>");
                    //                        }
                    //                    } else {
                    obj.element("probeName", probeCache.get(Long.parseLong(probeId)).getName());
                    obj.element("resName", sy[1]);
                    obj.element("ip", sy[3]);
                    obj.element("resTypeName", sy[4]);
                    obj.element("change", sy[2]);
                    //                    }
                    array.add(obj);
                }
                json.element("aaData", array);
                renderText(json.toString());
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e);
        }

        return null;
    }

    /**
     * 执行资源的发现   并完成添加操作
     * @return
     */
    public String doAddNetWorkDevices() {
        String probeId = request.getParameter("probeId");
        String flag = request.getParameter("flag");
        String parentId = request.getParameter("parentId");

        //获取网络设备资源列表 res-->attr
        List<String[]> nwList = getNwList(Long.parseLong(probeId), "getNetDeviceDetailList", null);

        //获取网络接口列表 res-->attr
        //        List<String[]> ifList = getNwList(probeId, "getNetIFDetailList", null);
        //        print(ifList);

        //获得类别列表kpiname 、typeid、name、port

        List<String[]> typeList = getNwList(Long.parseLong(probeId), "getResTypeList", null);
        if (typeList == null) {
            return null;
        }
        Set<Long> typeSet = new HashSet<Long>();
        for (String[] ary : typeList) {
            if (ary == null) {
                continue;
            }
            typeMap.put(ary[0], ary);
            subTypeMap.put(ary[1], ary);
            typeSet.add(Long.parseLong(ary[1]));
        }

        //先添加主资源列表
        List<Res> netResList = new ArrayList<Res>();
        addNetWorkRes(Long.parseLong(parentId), Long.parseLong(probeId), netResList, nwList, typeSet);

        //添加属性和端口子资源
        addAttrAndSubRes(Long.parseLong(probeId), netResList, nwList, null);

        //建立端口与设备的对应关系

        JSONObject json = new JSONObject();
        json.element("flag", "s");

        Struts2Utils.renderText(json.toString());

        return null;
    }

    /**
     * 添加网络设备
     * @param parentId
     * @param probeId
     * @param netResList 
     * @param nwList :inid、name、desc、ip、resTypeId -->sysoid、verdor、desc
     * @param netSet
     */
    public void addNetWorkRes(Long parentId, Long probeId, List<Res> netResList, List<String[]> nwList, Set<Long> netSet) {
        List<Res> addResList = new ArrayList<Res>();
        List<Res> delResList = new ArrayList<Res>();

        List<Res> noChangeList = new ArrayList<Res>();
        List<Res> oldList = resCache.getResInSet(netSet);
        List<ResAttrVal> attValList = new ArrayList<ResAttrVal>();
        for (String[] strs : nwList) {
            if (strs[0] == null || strs[0].length() < 1 || strs[3] == null || strs[3].length() < 1 || strs[4] == null || strs[4].length() < 1) {
                continue;
            }
            Res ores = resCache.getResIdByIId(strs[0]);
            if (ores != null) {
                if (!ores.getName().equals(strs[1]) || !ores.getIp().equals(strs[3])) {
                    ores.setName(strs[1]);
                    ores.setIp(strs[3]);
                    ResRelation rel = new ResRelation();
                    rel.setStartId(parentId);
                    rel.setEndId(ores.getId());
                    rel.setRelationTypeId(RelationConstants.SUPPORT);
                    resService.updateResource(ores, attValList, rel);
                    continue;
                } else if (ores.getResTypeId() != Long.parseLong(typeMap.get(strs[4])[1])) {
                    delResList.add(ores);
                } else {
                    noChangeList.add(ores);
                    netResList.add(ores);
                    continue;
                }
            }
            Res res = new Res();
            res.setInternalId(strs[0]);
            res.setName(strs[1]);
            res.setDesc(strs[2]);
            res.setIp(strs[3]);
            Long resType = Long.parseLong(typeMap.get(strs[4])[1]);
            res.setResTypeId(resType); //转成网络设备的类别
            res.setHealthStatus(ResConstants.NORMAL_USABLE);
            res.setPaused(ResConstants.RES_NOT_PAUSED);
            res.setDeleted(0);
            res.setHealthDegree(100);
            res.setProbeId(probeId);
            //新增的
            addResList.add(res);
            //新增 或  无变化的
            netResList.add(res);
        }

        //计算需删除的资源
        for (Res res : oldList) {
            boolean b = false;
            for (Res nres : noChangeList) {
                if (res.getId() == nres.getId()) {
                    b = true;
                    continue;
                }
            }
            if (!b) {
                delResList.add(res);
            }
        }

        System.out.println("netlist size = " + netResList.size());
        System.out.println("dele size=" + delResList.size());
        //删除资源
        for (Res dRes : delResList) {
            //            resService.deleteResource(parentId, dRes.getId())
            resService.deleteResAll(dRes.getId());
        }

        System.out.println("add size=" + addResList.size());
        //添加资源
        for (Res res : addResList) {
            resService.addResource(parentId, res, attValList, RelationConstants.SUPPORT);
        }

    }

    /**
     * 添加属性 和 端口子资源
     * @param probeId
     * @param netResList
     * @param nwList inid、name、desc、ip、resTypeId -->sysoid、verdor、desc
     * @param ifList inid、name、desc、resTypeId -->index、netmask、speedin、speedout、mac、connip、sysoid、admin、oper
     * @param ifset
     */
    public void addAttrAndSubRes(Long probeId, List<Res> netResList, List<String[]> nwList, Set<Long> ifset) {
        //添加属性  无则新加   有则比较后更新
        for (Res res : netResList) {
            List<Attribute> attributes = getAttributes(res.getResTypeId());
            int index = 5;
            for (Attribute attr : attributes) {
                Long attrId = attr.getId();
                ResAttrVal val = resAttrValCache.get(res.getId(), attrId);
                String[] strs = getNetDeviceAttr(res.getInternalId(), nwList);
                if (val == null || val.getAttrValue() == null || (!val.getAttrValue().equals(strs[index]) && val.getAttrValue() != null)) {
                    ResAttrVal attrV = new ResAttrVal();
                    attrV.setResId(res.getId());
                    attrV.setAttrId(attr.getId());
                    attrV.setAttrValue((strs[index] == null || strs[index].equals("null")) ? "" : strs[index]);
                    //                    attrV.setAttrValue(strs[index]);
                    attrV.setTime(Calendar.getInstance().getTime());
                    attributeService.saveResAttrVal(attrV);
                }
                index++;
            }
        }

        //添加网络子资源

        //List<Res> oldList = resCache.getResInSet(ifset);
        List<Res> allNoChangeList = new ArrayList<Res>();
        List<ResAttrVal> attValList = new ArrayList<ResAttrVal>();
        for (Res res : netResList) {
            FindResGroup group = FindResFactory.getInstance().getResGroup(res.getId());
            group.setFinish(false);
            group.build();
            List<Res> addResList = new ArrayList<Res>();
            List<Res> delResList = new ArrayList<Res>();
            List<Res> noChangeList = new ArrayList<Res>();
            String[] a = (String[]) subTypeMap.get(res.getResTypeId() + "");

            Long ifType = Long.parseLong(a[3]);

            List<String[]> ifStrList = getNwList(probeId, "getIFDetailList", res.getInternalId());
            if (ifStrList == null) {
                continue;
            }
            print(ifStrList);
            for (String[] strs : ifStrList) {
                group.getParents().checkChange(strs);
                //记录变化
                Map<Long, Long> addChangMap = new HashMap<Long, Long>();
                Map<Long, Long> updateChangMap = new HashMap<Long, Long>();
                //添加或者修改子资源
                List<FindResBean> beanList = group.getAllBeans();
                for (FindResBean bean : beanList) {
                    //                    if (bean.isChanged() || resCache.getResIdByIId(strs[4]) != null) {
                    if (bean.isChanged()) {
                        int changeType = bean.getChangeType();
                        if (resCache.getResIdByIId(strs[0]) == null) {
                            System.out.println("新加");
                            getChangeMap(bean, addChangMap);
                            //增加
                            changeAdd(bean);
                        } else if (changeType == FindResBean.CHANGE_MOD) {
                            getChangeMap(bean, updateChangMap);
                            System.out.println("修改");
                            //修改
                            changeMod(bean);
                        }
                    }
                }
                group.build();
                group.setFinish(true);
                //changeMap.put(iinId, flag == true ? "主资源属性变化了," + getChange(addChangMap, updateChangMap) : getChange(addChangMap, updateChangMap));
                //返回发生的变化

            }
        }
    }

    /**
     * 对端口数据分组
     * @param ifList inid、name、desc、ip=null、resTypeId=null -->index、netmask、speedin、speedout、mac、connip、sysoid、admin、oper
     * @return
     */
    public Map<String, List<String[]>> groupIfByNetdevice(List<String[]> ifList) {
        Pattern pattern = Pattern.compile("^IF-(.*)-\\d+$");
        Map<String, List<String[]>> map = new ConcurrentHashMap<String, List<String[]>>();
        for (String[] strs : ifList) {
            if (strs[0] == null || strs[0].length() < 1) {
                continue;
            }
            Matcher matcher = pattern.matcher(strs[0]);
            if (matcher.find()) {
                List<String[]> ary = map.get(matcher.group(1));
                if (ary == null) {
                    ary = new ArrayList<String[]>();
                    map.put(matcher.group(1), ary);
                }
                ary.add(strs);
            }
        }

        return map;
    }

    private void getChangeMap(FindResBean bean, Map<Long, Long> changMap) {
        if (changMap.containsKey(bean.getRes().getResTypeId())) {
            Long value = changMap.get(bean.getRes().getResTypeId()) == null ? 0 : changMap.get(bean.getRes().getResTypeId()) + 1;
            changMap.put(bean.getRes().getResTypeId(), value);
        } else {
            changMap.put(bean.getRes().getResTypeId(), 1l);
        }
    }

    private String getChange(Map<Long, Long> addChangMap, Map<Long, Long> updateChangMap) {
        StringBuffer change = new StringBuffer();
        if (addChangMap.keySet() != null && addChangMap.keySet().size() != 0) {
            change.append("增加了");
            for (Long resTypeId : addChangMap.keySet()) {
                Long num = addChangMap.get(resTypeId);
                change.append(num).append("个").append(resTypeCache.get(resTypeId).getName()).append(",");
            }
        }
        if (updateChangMap.keySet() != null && updateChangMap.keySet().size() != 0) {
            change.append("修改了");
            for (Long resTypeId : updateChangMap.keySet()) {
                Long num = updateChangMap.get(resTypeId);
                change.append(num).append("个").append(resTypeCache.get(resTypeId).getName()).append(",");
            }
        }
        if (change == null || change.length() == 0) {
            change.append("子资源无变化");
        } else {
            change.delete(change.lastIndexOf(","), change.length());
        }
        return change.toString();
    }

    private void changeAdd(FindResBean bean) {
        Res res = bean.getRes();
        res.setHealthStatus(ResConstants.NORMAL_USABLE);
        res.setPaused(ResConstants.RES_NOT_PAUSED);
        List<ResAttrVal> attValList = bean.getChangeAttrValues();
        Long parentResId = bean.getParent().getRes().getId();
        resService.addResource(parentResId, res, attValList, RelationConstants.FORM);
    }

    private void changeMod(FindResBean bean) {
        Res res = bean.getRes();
        List<ResAttrVal> attValList = bean.getChangeAttrValues();
        for (ResAttrVal attrVal : attValList) {
            ResAttrVal oldVal = attributeService.getResAttrVal(res.getId(), attrVal.getAttrId());
            ResAttrVal savedVal = null;
            if (oldVal != null) {
                //修改
                oldVal.setAttrValue(attrVal.getAttrValue());
                savedVal = oldVal;
            } else {
                //新增
                attrVal.setResId(res.getId());
                savedVal = attrVal;
            }
            attributeService.saveResAttrVal(savedVal);

        }

    }

    /**
     * 
     * @param inid
     * @param nwList
     * @return
     */
    public String[] getNetDeviceAttr(String inid, List<String[]> nwList) {
        if (inid == null) {
            return null;
        }
        for (String[] ary : nwList) {
            if (ary == null || ary.length < 8) {
                continue;
            }
            if (inid.equals(ary[0])) {
                return ary;
            }
        }

        return null;
    }

    /**
     * 获得一个类别的属性列表
     * @param resTypeId
     * @return
     */
    private List<Attribute> getAttributes(Long resTypeId) {
        List<Attribute> resTypeAttributes = ResTypeBean.get(resTypeId).attributes();
        return resTypeAttributes;
    }

    /**
     * 
     * @param list
     */
    private void print(List<String[]> list) {
        if (list == null) {
            return;
        }
        int i = 0;
        for (String[] arry : list) {
            if (i == 5) {
                break;
            }
            if (arry == null) {
                continue;
            }
            for (String str : arry) {
                System.out.print(str + "--");
            }
            System.out.println();
            i++;
        }
    }

    /**
     * 通过 MQ 获取到所有网络资源信息
     * @return
     */
    @SuppressWarnings("unchecked")
    private List<String[]> getNwList(Long probeId, String method, String param) {
        ServiceMessage message = new ServiceMessage();
        message.setSrvId("ResFindService");
        message.setMethod(method);
        if (param != null && param.length() > 1) {
            message.setParams(new Object[] { param });
        }
        Object result = null;
        try {
            result = Messenger.getInstance().sendSyncMessage(probeId, message);
        } catch (Exception e) {
            logger.error(e);
        }
        if (result == null) {
            return null;
        }
        return (List<String[]>) result;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @Override
    public Object getModel() {
        return entity;
    }

    @Override
    public String list() throws Exception {
        return null;
    }

    @Override
    public String input() throws Exception {
        return null;
    }

    @Override
    public String save() throws Exception {
        return null;
    }

    @Override
    public String delete() throws Exception {
        return null;
    }

    @Override
    protected void prepareModel() throws Exception {

    }

    @SuppressWarnings("rawtypes")
    class ProbeSort implements Comparator {
        @Override
        public int compare(Object obj1, Object obj2) {
            Probe res1 = (Probe) obj1;
            Probe res2 = (Probe) obj2;
            if (Math.abs(res1.getStatus() - 3) > Math.abs(res2.getStatus() - 3)) {
                return 1;
            } else {
                return 0;
            }
        }
    }

    public static void main(String[] args) {
        Pattern pattern = Pattern.compile("^IF-(.*)-\\d+$");
        Matcher mat = pattern.matcher("IF-sinodata-www-009");

        System.out.println(mat.find());
        System.out.println(mat.group(1));

    }

}
